#include <windows.h>
#include"resource.h"
#include"spaghetti.h"
const char g_szClassName[] = "myWindowClass";
HINSTANCE hInst;
POINT point[3];

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK Random(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK User(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void grafic(double timpara,double timbarb,HWND hwnd,HDC hdc);
void stergere_grafic(HDC hdc, HWND hwnd);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = CS_BYTEALIGNWINDOW|CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  =MAKEINTRESOURCE(IDR_MENU1);
   wc.lpszClassName ="myWindowClass";
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx( WS_EX_CLIENTEDGE,"myWindowClass","Spaghetti stack",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 840, 520,NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd,  SW_MAXIMIZE);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

	POINT p1;
	PAINTSTRUCT ps;
	HBRUSH perie,Brush,bBrush,rBrush; 
	HPEN Pen,hPen;
	HDC hdc=NULL;
	int ok,i;
	int wmId, wmEvent;


    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
		case WM_CREATE:
		{
			HWND buton1=CreateWindowEx(NULL,"BUTTON","Random",WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,20,50,200,40,hwnd,(HMENU)IDC_BUTON1,GetModuleHandle(NULL),NULL);
			HWND buton2=CreateWindowEx(NULL,"BUTTON","User",WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,20,150,200,40,hwnd,(HMENU)IDC_BUTON2,GetModuleHandle(NULL),NULL);
			}

		break;
	
		case WM_PAINT:
				hdc = BeginPaint(hwnd, &ps);
				hPen = CreatePen(PS_SOLID,2,RGB(0,0,0));
				bBrush = CreateSolidBrush(RGB(0,200,200));
				rBrush = CreateSolidBrush(RGB(255,0,0));

				SelectObject(hdc, hPen);
				MoveToEx(hdc,320, 600, NULL);
				LineTo(hdc,320, 100);
				point[0].x=320;
				point[0].y=100;
				point[1].x=315;
				point[1].y=110;
				point[2].x=325;
				point[2].y=110;
				Polygon(hdc,point,3);

				MoveToEx(hdc,320, 600, NULL);
				LineTo(hdc,1320, 600);
				point[0].x=1320;
				point[0].y=600;
				point[1].x=1310;
				point[1].y=595;
				point[2].x=1310;
				point[2].y=605;
				Polygon(hdc,point,3);
				ok=1;
				for(i=595;i>120;i=i-5)
					if(i%25==0)
					{
						ok=1;
						MoveToEx(hdc,310, i, NULL);
						LineTo(hdc,330, i);
					}
					
				EndPaint(hwnd, &ps);
		break;
		case WM_COMMAND:
			wmId    = LOWORD(wParam);
			wmEvent = HIWORD(wParam);
			switch (wmId)
			{
			case  ID_NEW_RANDOM:
			{
				stergere_grafic(hdc,hwnd);
				DialogBox(hInst, MAKEINTRESOURCE(IDD_RANDOM), hwnd,Random);
				if((timpara!=0)&&(timparb!=0))
					grafic(timpara,timparb,hwnd,hdc);
			}
			break;
			case  ID_NEW_USER:
				{
					nr_cautari=0;
					nr_pop=0;
					nr_push=0;
					DialogBox(hInst, MAKEINTRESOURCE(IDD_USER), hwnd,User);
				}
			break;
			case ID_FILE_EXIT:

				DestroyWindow(hwnd);
			break;
			case IDC_BUTON1:
				{
				stergere_grafic(hdc,hwnd);
				DialogBox(hInst, MAKEINTRESOURCE(IDD_RANDOM), hwnd,Random);
				if((timpara!=0)&&(timparb!=0))
					grafic(timpara,timparb,hwnd,hdc);
			}
			break;
			case IDC_BUTON2:
				{
					nr_cautari=0;
					nr_pop=0;
					nr_push=0;
					DialogBox(hInst, MAKEINTRESOURCE(IDD_USER), hwnd,User);
				}
			break;
			}

        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

INT_PTR CALLBACK Random(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK)
		{
			int bState;
				char a[11];
				GetDlgItemText(hDlg,IDC_EDIT1,a,6);
				int i;
				for(i=0;i<strlen(a);i++)
					if((a[i]<48)||(a[i]>57))
					{
						MessageBox(hDlg,"Introduceti numai numere naturale","Eroare",0);
						return (INT_PTR)TRUE;
					}
				number=atoi(a);
				random();
				EndDialog(hDlg, LOWORD(wParam));	
				return (INT_PTR)TRUE;
		}
		if (LOWORD(wParam) == IDC_BUTTON2)
		{
			int bState;
				char a[11];
				GetDlgItemText(hDlg,IDC_EDIT1,a,6);
				int i;
				for(i=0;i<strlen(a);i++)
					if((a[i]<48)||(a[i]>57))
					{
						MessageBox(hDlg,"Introduceti numai numere naturale","Eroare",0);
						return (INT_PTR)TRUE;
					}
				number=atoi(a);
				ok=1;
				random();
				ok=0;
				EndDialog(hDlg, LOWORD(wParam));	
				return (INT_PTR)TRUE;
		}
		if(LOWORD(wParam)==IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
	
		break;
	}
	return (INT_PTR)FALSE;

}

INT_PTR CALLBACK User(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);

	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		//Adauga in stiva
		if (LOWORD(wParam) == IDC_BUTTON1)
		{

			int bState;
				char a[6];
				GetDlgItemText(hDlg,IDC_EDIT1,a,6);
				int i;
				for(i=0;i<strlen(a);i++)
					if((a[i]<48)||(a[i]>57))
					{
						MessageBox(hDlg,"Introduceti numai numere naturale","Eroare",0);
						return (INT_PTR)TRUE;
					}
					
						int x=atoi(a);
						push_sp(x);	// stiva spaghetti
						push_st(x);	// stiva normala
						vec_adaugari[nr_push]=x;
						nr_push++;
		}
		//Cauta din stiva
		if (LOWORD(wParam) == IDC_BUTTON2)
		{

			int bState;
				char a[6];
				GetDlgItemText(hDlg,IDC_EDIT1,a,2);
				int i;
				for(i=0;i<strlen(a);i++)
					if((a[i]<48)||(a[i]>57))
					{
						MessageBox(hDlg,"Introduceti numai numere naturale","Eroare",0);
						return (INT_PTR)TRUE;
					}

						int x=atoi(a);
						int rez_sp;			// daca s-a gasit sau nu valoarea cautata in stiva spaghetti
						int rez_st;			// daca s-a gasit sau nu valoarea cautata in stiva normala

						rez_sp=cautare_spaghetti(x);
						rez_st=cautare_stiva_normala(x);

						vec_cautari[nr_cautari]=x;
						nr_cautari++;
						if(rez_sp==-1)
						{
							MessageBox(hDlg,"Elementul cautat nu a fost introdus","Answer",0);
							return (INT_PTR)TRUE;
						}
						char c[174];
						if(rez_sp==1)
							sprintf(c,"Elementul '%d' se afla in istoria stivei spaghetti pe pozitia %d",x,loc_sp);
						else
							sprintf(c,"Elementul '%d' se afala in stiva spaghetti pe pozitia %d",x,loc_sp);
						char c2[87];
						if(rez_st==1)
							sprintf(c2,", iar in stiva normala se gaseste pe pozitia %d.",loc_st);
						else
							sprintf(c2,", iar in stiva normala nu s-a gasit.");
						strcat(c,c2);
						MessageBox(hDlg,c,"Answer",0);

						
// explicatii: poti avea la dispozitie aceleasi informatii ca la random(), insa in plus apar urmatoarele variabile:
	// rez_sp este -1 daca nu s-a gasit, 1 daca s-a gasit in history si 0 daca s-a gasit in stiva spaghetti principala
	// rez_st este 0 daca nu s-a gasit si 1 daca s-a gasit in stiva normala
	// loc_sp e un integer care memoreaza locul unde s-a gasit valoarea in history daca rez_sp este 1 respectiv in  spaghetti daca rez_sp este 0
	// loc_st este un intreg ce memoreaza locul unde s-a gasit valoarea in stiva normala
					
		}
		//Stergere din stiva
		if (LOWORD(wParam) == IDC_BUTTON3)
		{

						int x;
						pop_st(&x);
						pop_sp(&x);
						vec_pop[nr_pop]=x;
						nr_pop++;
					
		}
		if(LOWORD(wParam)==IDC_BUTTON4)
		{
			EndDialog(hDlg, LOWORD(wParam));
			eliberare_structuri();
			return (INT_PTR)TRUE;
		}
	
		break;
	}
	return (INT_PTR)FALSE;

}

void grafic(double timpara,double timparb,HWND hwnd,HDC hdc)
{
    stergere_grafic(hdc,hwnd);
	HPEN hPen = CreatePen(PS_SOLID,4,RGB(0,0,0));
	HBRUSH bBrush = CreateSolidBrush(RGB(100,220,200));
	hdc=GetDC(hwnd);
	
		SelectObject(hdc,hPen);
		SelectObject(hdc, bBrush);

		char s[100];
		s[0]=' ';
		s[1]=NULL;

		double 	t=timpara;
	
		char q[30];
			sprintf(q,"%f ",t);
			strcat(s,q);
			strcat(s," s");
			TextOut(hdc,340,660,s,strlen(s));		// timpul spaghetti
			sprintf(q,"%s","Timp stiva spaghetti");
			TextOut(hdc, 700, 105,q, strlen(q));

			s[0]=' ';
			s[1]=NULL;
			t=timparb;
			sprintf(q,"%f ",t);
			strcat(s,q);
			strcat(s," s");
			TextOut(hdc,470,660,s,strlen(s));
			sprintf(q,"%s","Timp stiva normala");
			TextOut(hdc, 700, 250,q, strlen(q));

			bBrush = CreateSolidBrush(RGB(100,220,200));
			SelectObject(hdc, bBrush);
			Rectangle(hdc,600,105,690,123);

			bBrush = CreateSolidBrush(RGB(0,220,100));
			SelectObject(hdc, bBrush);
			Rectangle(hdc,600,250,690,268);

		double inaltime;		// reprezinta inaltimea graficului mai mic
		if(timpara > timparb)		// in acest caz timpul spaghetti este mai mare
		{
			bBrush = CreateSolidBrush(RGB(100,220,200));
			SelectObject(hdc, bBrush);
			Rectangle(hdc,340,600,390,105);
			
			
			inaltime=(timparb*495)/timpara;		// regula de trei simpla, iar 495 este inaltimea maxima, adica inaltimea timpului mai mare
			bBrush = CreateSolidBrush(RGB(0,220,100));
			SelectObject(hdc, bBrush);
			Rectangle(hdc,470,600,520,600 - inaltime);
		}
		else		// in acest caz timpul stiva normala este mai mare
		{
			bBrush = CreateSolidBrush(RGB(100,220,200));
			SelectObject(hdc, bBrush);
			Rectangle(hdc,470,600,520,105);

			inaltime=(timpara*495)/timparb;		// regula de trei simpla, iar 495 este inaltimea maxima, adica inaltimea timpului mai mare
			bBrush = CreateSolidBrush(RGB(0,220,100));
			SelectObject(hdc, bBrush);
			Rectangle(hdc,340,600,390,600 - inaltime);
		}
}
void stergere_grafic(HDC hdc, HWND hwnd)
{

	HDC hdc1=NULL;
	hdc1=GetDC(hwnd);
	HPEN Pen1=CreatePen(PS_SOLID,1,RGB(255,255,255));
	HBRUSH Brush1 = CreateSolidBrush(RGB(255,255,255));
	SelectObject(hdc1,Pen1);
	SelectObject(hdc1, Brush1);
	Rectangle(hdc1,335,599,550,0);
}